//     Zepto.js 
//     (c) 2010-2014 Thomas Fuchs 
//     Zepto.js may be freely distributed under the MIT license. 


;(function($, undefined){ 
  var prefix = '', eventPrefix, endEventName, endAnimationName, 
    vendors = { Webkit: 'webkit', Moz: '', O: 'o' }, 
    document = window.document, testEl = document.createElement('div'), 
    supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i, 
     transform, 
     transitionProperty, transitionDuration, transitionTiming, transitionDelay, 
     animationName, animationDuration, animationTiming, animationDelay, 
     cssReset = {} 
 

   function dasherize(str) { return str.replace(/([a-z])([A-Z])/, '$1-$2').toLowerCase() } 
   function normalizeEvent(name) { return eventPrefix ? eventPrefix + name : name.toLowerCase() } 
 

   $.each(vendors, function(vendor, event){ 
     if (testEl.style[vendor + 'TransitionProperty'] !== undefined) { 
       prefix = '-' + vendor.toLowerCase() + '-' 
       eventPrefix = event 
       return false 
     } 
   }) 
 

   transform = prefix + 'transform' 
   cssReset[transitionProperty = prefix + 'transition-property'] = 
   cssReset[transitionDuration = prefix + 'transition-duration'] = 
   cssReset[transitionDelay    = prefix + 'transition-delay'] = 
   cssReset[transitionTiming   = prefix + 'transition-timing-function'] = 
   cssReset[animationName      = prefix + 'animation-name'] = 
   cssReset[animationDuration  = prefix + 'animation-duration'] = 
   cssReset[animationDelay     = prefix + 'animation-delay'] = 
   cssReset[animationTiming    = prefix + 'animation-timing-function'] = '' 
 

   $.fx = { 
     off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined), 
     speeds: { _default: 400, fast: 200, slow: 600 }, 
     cssPrefix: prefix, 
     transitionEnd: normalizeEvent('TransitionEnd'), 
     animationEnd: normalizeEvent('AnimationEnd') 
   } 
 

   $.fn.animate = function(properties, duration, ease, callback, delay){ 
     if ($.isFunction(duration)) 
       callback = duration, ease = undefined, duration = undefined 
     if ($.isFunction(ease)) 
       callback = ease, ease = undefined 
     if ($.isPlainObject(duration)) 
       ease = duration.easing, callback = duration.complete, delay = duration.delay, duration = duration.duration 
     if (duration) duration = (typeof duration == 'number' ? duration : 
                     ($.fx.speeds[duration] || $.fx.speeds._default)) / 1000 
     if (delay) delay = parseFloat(delay) / 1000 
     return this.anim(properties, duration, ease, callback, delay) 
   } 
 

   $.fn.anim = function(properties, duration, ease, callback, delay){ 
     var key, cssValues = {}, cssProperties, transforms = '', 
         that = this, wrappedCallback, endEvent = $.fx.transitionEnd, 
         fired = false 
 

     if (duration === undefined) duration = $.fx.speeds._default / 1000 
     if (delay === undefined) delay = 0 
     if ($.fx.off) duration = 0 
 

     if (typeof properties == 'string') { 
       // keyframe animation 
       cssValues[animationName] = properties 
       cssValues[animationDuration] = duration + 's' 
       cssValues[animationDelay] = delay + 's' 
       cssValues[animationTiming] = (ease || 'linear') 
       endEvent = $.fx.animationEnd 
     } else { 
       cssProperties = [] 
       // CSS transitions 
       for (key in properties) 
         if (supportedTransforms.test(key)) transforms += key + '(' + properties[key] + ') ' 
         else cssValues[key] = properties[key], cssProperties.push(dasherize(key)) 
 

       if (transforms) cssValues[transform] = transforms, cssProperties.push(transform) 
       if (duration > 0 && typeof properties === 'object') { 
         cssValues[transitionProperty] = cssProperties.join(', ') 
         cssValues[transitionDuration] = duration + 's' 
         cssValues[transitionDelay] = delay + 's' 
         cssValues[transitionTiming] = (ease || 'linear') 
       } 
     } 
 

     wrappedCallback = function(event){ 
       if (typeof event !== 'undefined') { 
         if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from "below" 
         $(event.target).unbind(endEvent, wrappedCallback) 
       } else 
         $(this).unbind(endEvent, wrappedCallback) // triggered by setTimeout 
 

       fired = true 
       $(this).css(cssReset) 
       callback && callback.call(this) 
     } 
     if (duration > 0){ 
       this.bind(endEvent, wrappedCallback) 
       // transitionEnd is not always firing on older Android phones 
       // so make sure it gets fired 
       setTimeout(function(){ 
         if (fired) return 
         wrappedCallback.call(that) 
       }, (duration * 1000) + 25) 
     } 
 

     // trigger page reflow so new elements can animate 
     this.size() && this.get(0).clientLeft 
 

     this.css(cssValues) 
 

     if (duration <= 0) setTimeout(function() { 
       that.each(function(){ wrappedCallback.call(this) }) 
     }, 0) 
 

     return this 
   } 
 

   testEl = null 
 })(Zepto) 
